<html lang="en-US">

<head>
    
<title>上帝视角：Go 语言设计失误，缺乏远见？ - 花落雨忧</title>

<meta property="og:title" content="上帝视角：Go 语言设计失误，缺乏远见？ - 花落雨忧">



    



    
    <meta property="description" content="大家好，我是煎鱼。
前段时间我有一个朋友在某乎上摸鱼时，给我甩来一个主题为《golang 设计者是如何偿还技术债的》链接。
说是让我学习、围观一下社区观点，早日好修成正果，本鱼表示满脸问号。
原回答如下图：
主要是以极短的话语表述 Go 语言的 “泛型、异常、channel、annotation、模块依赖” 的设计是失误的。
说是没有向各种编程语言的 “最佳实践” 各取所需。
[&amp;hellip;] &amp;hellip;">
    <meta property="og:description" content="大家好，我是煎鱼。
前段时间我有一个朋友在某乎上摸鱼时，给我甩来一个主题为《golang 设计者是如何偿还技术债的》链接。
说是让我学习、围观一下社区观点，早日好修成正果，本鱼表示满脸问号。
原回答如下图：
主要是以极短的话语表述 Go 语言的 “泛型、异常、channel、annotation、模块依赖” 的设计是失误的。
说是没有向各种编程语言的 “最佳实践” 各取所需。
[&amp;hellip;] &amp;hellip;">
    






<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1">

<link rel="shortcut icon" href="https://www.lican.asia/logo/logo.png" type="image/x-icon" />



<link rel="stylesheet" href="/css/style.min.css" />

<link rel="stylesheet" href="/css/reset.min.css" />




<script src="https://www.lican.asia/js/highlight.min.js"></script>

<script>
hljs.configure({ ignoreUnescapedHTML: true })
hljs.highlightAll();
</script>


<script src="https://www.lican.asia/js/jquery.min.js"></script>




<link href="https://www.lican.asia/css/hugo-code.min.css" rel="stylesheet" />



    <style>
        .post-content img {
            max-width: 400px;
        }
    </style>
</head>

<body id="period" class="home blog">
    <a class="skip-content" href="#main">Press "Enter" to skip to content</a>
    <div id="overflow-container" class="overflow-container">
        <header class="site-header" id="site-header" role="banner">
    <div class="max-width">
        <div id="title-container" class="title-container">
            <div id="site-title" class="site-title"><a href="/">花落雨忧</a></div>
            <p class="tagline">思所及 力所行 方为真.</p>
        </div>
        
        <div id="menu-primary-container" class="menu-primary-container">
            <div class="icon-container">
            </div>
            <div id="menu-primary" class="menu-container menu-primary" role="navigation">
                <nav class="menu">
                    <ul id="menu-primary-items" class="menu-primary-items">
                        
                        
                        <li id="menu-item-0"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/posts" aria-current="page" tabindex="0">首页</a></li>
                        
                        <li id="menu-item-1"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/tech/" aria-current="page" tabindex="1">技术文档</a></li>
                        
                        <li id="menu-item-2"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/article/" aria-current="page" tabindex="2">文章</a></li>
                        
                        <li id="menu-item-3"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/project/" aria-current="page" tabindex="3">项目</a></li>
                        
                        <li id="menu-item-4"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/about/" aria-current="page" tabindex="4">关于</a></li>
                        
                    </ul>
                </nav>
            </div>
        </div>
    </div>
</header>

        <div id="primary-container" class="primary-container">
            <div class="max-width">
                <section id="main" class="main" role="main">
                    <div id="loop-container" class="loop-container">
                        <div
                            class="post type-post status-publish format-standard hentry entry">
                            <article>
                                <div class="post-container">
                                    <div class="post-header">
                                        <h2 class="post-title">
                                            <a href="/posts/posts/go/go-design/">上帝视角：Go 语言设计失误，缺乏远见？</a>
                                        </h2>
                                        
                                        <div class="post-byline">Published on
                                            <a class="date" href="javascript:;">2021/12/31</a>
                                            
                                            
                                            
                                            
                                            
                                        
                                    </div>
                                    <div class="post-content">
                                        <p>大家好，我是煎鱼。</p>
<p>前段时间我有一个朋友在某乎上摸鱼时，给我甩来一个主题为《golang 设计者是如何偿还技术债的》链接。</p>
<p>说是让我学习、围观一下社区观点，早日好修成正果，本鱼表示满脸问号。</p>
<p>原回答如下图：</p>
<p><img src="https://files.mdnice.com/user/3610/4bbdfe91-b98e-4ae1-bcc6-aa5fc50cd184.png" alt=""></p>
<p>主要是以极短的话语表述 Go 语言的 “泛型、异常、channel、annotation、模块依赖” 的设计是失误的。</p>
<p>说是没有向各种编程语言的 “最佳实践” 各取所需。</p>
<h2 id="那些故事">那些故事</h2>
<p>刚好煎鱼也入门 Go 没几天，偶尔翻过 issues 和 proposal，看了一点点历史事件。</p>
<p><img src="https://files.mdnice.com/user/3610/3213b564-1a53-4dcf-9b69-4f4359bd50db.png" alt="图来自 Introduction to Golang"></p>
<p>也从我的观点来围观一下 Go 官方这些年为特性挣扎过的那些事。</p>
<p>涉及：</p>
<ol>
<li>泛型。</li>
<li>错误处理。</li>
<li>依赖管理。</li>
<li>注解。</li>
</ol>
<h3 id="泛型">泛型</h3>
<p><strong>为什么 Go 语言这么久都没有泛型</strong>，是不是 Go 官方不够 “聪明”，抄作业都不会抄。这显然是不对的。</p>
<p>有如下几点原因：</p>
<ol>
<li>泛型本质上并不是绝对的必需品。</li>
<li>泛型不是 Go 语言的早期目标。</li>
<li>其他 feature 更重要，把精力放在这些上面，Go 团队人力很有限的。</li>
</ol>
<h4 id="历史尝试">历史尝试</h4>
<p>在以往的尝试中，Go 团队有人进行过不少的泛型 proposal 试验。基本时间线（via @changkun）如下：</p>
<table>
<thead>
<tr>
<th>简述</th>
<th>时间</th>
<th>作者</th>
</tr>
</thead>
<tbody>
<tr>
<td>Type Functions</td>
<td>2010年</td>
<td>Ian Lance Taylor</td>
</tr>
<tr>
<td>Generalized Types</td>
<td>2011年</td>
<td>Ian Lance Taylor</td>
</tr>
<tr>
<td>Generalized Types v2</td>
<td>2013年</td>
<td>Ian Lance Taylor</td>
</tr>
<tr>
<td>Type Parameters</td>
<td>2013年</td>
<td>Ian Lance Taylor</td>
</tr>
<tr>
<td>go:generate</td>
<td>2014年</td>
<td>Rob Pike</td>
</tr>
<tr>
<td>First Class Types</td>
<td>2015年</td>
<td>Bryan C.Mills</td>
</tr>
<tr>
<td>Contracts</td>
<td>2018年</td>
<td>Ian Lance Taylor, Robert Griesemer</td>
</tr>
<tr>
<td>Contracts</td>
<td>2019年</td>
<td>Ian Lance Taylor, Robert Griesemer</td>
</tr>
<tr>
<td>Redundancy in Contracts(2019)&rsquo;s Design</td>
<td>2019年</td>
<td>Ian Lance Taylor, Robert Griesemer</td>
</tr>
<tr>
<td>Constrained Type Parameters(2020, v1)</td>
<td>2020年</td>
<td>Ian Lance Taylor, Robert Griesemer</td>
</tr>
<tr>
<td>Constrained Type Parameters(2020, v2)</td>
<td>2020年</td>
<td>Ian Lance Taylor, Robert Griesemer</td>
</tr>
<tr>
<td>Constrained Type Parameters(2020, v3)</td>
<td>2020年</td>
<td>Ian Lance Taylor, Robert Griesemer</td>
</tr>
</tbody>
</table>
<p>我们观察一下，10 年过去了，Ian Lance Taylor 依然在开展泛型提案，持续地在思考着 Go 泛型。</p>
<p>坚持思考，这一点值得我们学习。</p>
<p>对 Go 泛型历史有兴趣的读者可以看看《<a href="https://mp.weixin.qq.com/s/ftmuA9g7QPAwSwiswRuSuw">为什么 Go 的泛型一拖再拖？</a>》，给了明确完整的内容介绍和过程描述了。</p>
<h3 id="下一步计划">下一步计划</h3>
<p>在 2021 年尾巴的我们，明年（2022年） <strong>Go1.18 左右就可以见到 Go 泛型，基本跑不了。</strong></p>
<p>想想就激动，如下图（此刻是 4 个月后）：</p>
<p><img src="https://files.mdnice.com/user/3610/934613fa-2564-4f26-bd40-bb309bd48dcf.png" alt="图来自网上"></p>
<p>在出来前可以看看《<a href="https://mp.weixin.qq.com/s/Pf7YuFpwbldSB60DDCBtlA">Go 1.17 支持泛型了？具体怎么用</a>》，可以作为玩具用了。</p>
<p>接下来可以预见泛型出来后，一堆工具库和数据结构很大可能会被逐步改写，像是《<a href="https://mp.weixin.qq.com/s/D7u7nxixctoFIL-Pch0zvw">Go 提案：增加泛型版 slices 和 maps 新包</a>》，早已摩拳擦掌。</p>
<p>届时 Go 源码类别的书的部分内容也会失时效，需要关注 Go 版本的时效性。</p>
<h3 id="错误处理">错误处理</h3>
<p>在日常工程中，我们写的、看到最多的可能就是这一段标志性 Go 代码：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">x</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">foo</span>()
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>   <span style="color:#75715e">// handle error
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> }
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">y</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">foo</span>()
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>   <span style="color:#75715e">// handle error
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> }
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">z</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">foo</span>()
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>   <span style="color:#75715e">// handle error
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> }
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">s</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">foo</span>()
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>   <span style="color:#75715e">// handle error
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span> }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>这是在业内被吐槽的最多的，甚至都可以用来作为 Gopher 的互认。</p>
<h4 id="设计方向">设计方向</h4>
<p>那 Go 是瞎设计的吗，就粗制滥造，搞个错误 err 的返回约定惯例。像是：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-golang" data-lang="golang"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">foo</span>() <span style="color:#a6e22e">err</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>其实并不是，Go 团队在设计上有意识地选择了<strong>显式</strong>的设计方向，如下：</p>
<ul>
<li>使用显式错误结果。</li>
<li>使用显式错误检查。</li>
</ul>
<p>这和其他语言不一样 ，是由于 Go 团队也认识到了异常处理的不可见错误检查所带来的问题。</p>
<p>设计草案有一部分是受到了这些问题的启发。如下：</p>
<p><img src="https://files.mdnice.com/user/3610/9c308232-631e-4aa3-b265-85daf2b9909d.png" alt=""></p>
<p>目前 Go 官方也没有打算去掉 “显式” 这一做法，新版 Go2 错误处理的核心目标是：“<strong>错误检查更加轻便，减少专门用于错误检查的 Go 程序代码的数量和所花费的时间</strong>。”。</p>
<p>从 Go2 的趋势来看，主要是增加关键字和修饰来解决这个问题，相当于是堆积木了，而不是直接把他干掉的。</p>
<p>这在 Go 核心团队内是非常明确的。</p>
<h4 id="进一步深入">进一步深入</h4>
<p>对 Go 语言错误处理还想进一步深入的，推荐看下面这几篇文章：</p>
<ul>
<li>《<a href="https://mp.weixin.qq.com/s/XILveKzh07BOQnqxYDKQsA">先睹为快，Go2 Error 的挣扎之路</a>》</li>
<li>《<a href="https://mp.weixin.qq.com/s/ixBMcAgqW51I0r_hkw5l5A">Go errors 不会有进一步的改进计划</a>》</li>
<li>《<a href="https://mp.weixin.qq.com/s/Ey-yqIq__wpaLTlBAOHjxg">你对 Go 错误处理的 4 个误解！</a>》</li>
</ul>
<h3 id="依赖管理">依赖管理</h3>
<p>Go 语言在一开始是完全基于 GOPATH 作为依赖管理的模式，当时也闹了不少的争议出来。有以下核心问题：</p>
<ol>
<li>依赖要手动拉取和下载，没有强版本化的概念，开发者很难受（例如：不兼容升级、要拉取同一份）。</li>
<li>依赖和工程代码必须在 GOPATH 下才能运行，不能任意摆放。</li>
</ol>
<p>所以在 Go1.0~Go1.11 中，各路神仙发招，社区出现了各种诸如 dep、glide、godep 等依赖包管理工具。</p>
<h4 id="时间线">时间线</h4>
<p>后续 Go 团队在 Russ Cox 的强势推进下，力排众议，推动 Go modules 的发展：</p>
<p><img src="https://files.mdnice.com/user/3610/66291d6e-b10b-42db-9242-d5e16eb94237.png" alt=""></p>
<p>时间线如下：</p>
<ul>
<li>Go1.11 起开始推进 Go modules（前身 vgo）。</li>
<li>Go1.13 起不再推荐使用 GOPATH 的使用模式。</li>
<li>Go1.14 表示已经准备好，可以用在生产上（ready for production）了。</li>
</ul>
<h4 id="为什么这么晚">为什么这么晚</h4>
<p>为什么 Go modules 这么晚才诞生，这是不是就是 Go 团队的设计失误呢？</p>
<p>我认为，是也不是。</p>
<p>Go 的诞生一开始是为了解决 Google 几位大佬自己的痛点。</p>
<p>在 Google 的依赖管理上，本身是大仓库（Monorepo）的模式，企业内部有自己一整套工具和流程，设计之初没有这块的强诉求。</p>
<p>如下：</p>
<p><img src="https://files.mdnice.com/user/3610/c589a0af-e0c1-4e9b-83c2-899369c9fa8e.jpg" alt="图来自 Mono Repo vs Multi Repo"></p>
<p>有兴趣的读者详细可阅读《<a href="https://dl.acm.org/doi/epdf/10.1145/2854146">Why Google Stores Billions of Lines of Code in a Single Repository</a>》，</p>
<p>Go 在社区开源后，大规模使用后这个问题就爆发了，社区自行释出了方案。可惜，五花八门，也都没有解决好。官方队伍就自己上手了。</p>
<p>要知道，没有技术方案是完美的。Go modules 也被不少人所吐槽，存在争议。</p>
<h4 id="进一步深入-1">进一步深入</h4>
<p>想更进一步深入 Go modules 的小伙伴，可以看看下述文章：</p>
<ul>
<li>《<a href="https://mp.weixin.qq.com/s/6gJkSyGAFR0v6kow2uVklA">Go Modules 终极入门和历史</a>》</li>
<li>《<a href="https://mp.weixin.qq.com/s/jpp7vs3Fdg4m15P1SHt1yA">干货满满的 Go Modules 和 goproxy.cn</a>》</li>
</ul>
<h3 id="注解">注解</h3>
<p>Go 开发者中有大部分同学都有其他语言的使用经验。在其他语言中，注解是一个强大的工具，没得用会很不习惯。</p>
<p><img src="https://files.mdnice.com/user/3610/9061ff09-9776-4a74-9550-fc5a4f17f824.png" alt="图片来自网络"></p>
<p>甚至有听过没有注解，就自嘲不会 “写” 代码了，所以一上来就找 Go 语言的注解怎么用了。</p>
<h4 id="一些疑惑">一些疑惑</h4>
<p>我有一个朋友，经常会听到如下疑惑，甚至无奈的发问：</p>
<ul>
<li>“怎么样在函数前声明，直接开启事务？”</li>
<li>&ldquo;为什么 Java 可以完美注解，Go 就不行，难以理解，我无法接受&hellip;&rdquo;</li>
<li>“那 Go 支持什么程度的注解？”</li>
</ul>
<p>Go 的 “注解” 支撑的非常有限，基本都是 <code>//go build</code>、<code>go:generate</code> 这类辅助，达不到标准的装饰器的作用。</p>
<h4 id="为什么不支持">为什么不支持</h4>
<p>没有全面的支持注解来做装饰器，显然不算 Go 的设计失误，这是刻意为之，这是与错误处理的设计理念相关联。</p>
<p>Go issues 上有人提过类似的提案：</p>
<p><img src="https://files.mdnice.com/user/3610/9695f163-65e8-456a-8dce-bb8551739016.png" alt=""></p>
<p>Go Contributor @ianlancetaylor 给出了明确的答复，Go在设计上更倾向于明确的、显式的编程风格。</p>
<p>优缺点如下：</p>
<ul>
<li>优势：不知道 Go 能从添加装饰器中得到什么好处，没能在 issues 上明确论证。</li>
<li>缺点：是明确的，会存在意外设置的情况。</li>
</ul>
<p>因如下原因，没有接受注解：</p>
<ul>
<li>对比现有代码方法，这种装饰器的新的方法没有提供比现有方法更多的优势，大到足矣推翻原有的设计思路。</li>
<li>社区内的投票，支持的也很少（基于表情符号的投票），用户反馈不多。</li>
</ul>
<p>可能有小伙伴会说了，有注解做装饰器了，代码会简洁不少。</p>
<p>但其实 Go 团队的态度很明确：</p>
<p><img src="https://files.mdnice.com/user/3610/bb357e12-9b15-4729-9381-977d164b6b04.png" alt=""></p>
<p>Go 认为<strong>可读性更重要</strong>，如果只是额外多写一点代码，在权衡后，还是可以接受的。</p>
<p>如果想自己在 Go 中实现完整注解的，可以详细阅读《<a href="https://mp.weixin.qq.com/s/hrsagmDtjt6r9fJKf8SUcQ">Go：我有注解，Java：不，你没有！</a>》，可以给到你一些思路。</p>
<h2 id="偿还的过程">偿还的过程</h2>
<p>如果是在职场中工作多年的小伙伴，其实不难发现 Go 的发展史和业务的发展节奏是类似的。</p>
<p>在社区中吐槽的主要是两块，如下：</p>
<ul>
<li>为什么这个功能不如此设计？</li>
<li>这个功能为什么没有支持？</li>
</ul>
<h3 id="不如此设计">不如此设计</h3>
<p>为什么 Go 语言不如此设计？经典的像是 Go 的错误处理（error），很多小伙伴会<strong>先入为主</strong>，以其他语言的最佳实践，要教 Go 团队设计，要 throw，要 catch！</p>
<p>其实想一下，我们做一个业务，这个业务就是 Go 语言。我们需要先做业务建模，确定 Go 的核心思想，才能持续的迭代和设计。</p>
<p>Go 语言的设计定义很明显是：<strong>既要简单、还要显式，不能有隐式、要避免复杂</strong>，所以社区传递的是 “<strong>less is more</strong>” 的设计理念。</p>
<p>这么想，很多提案的落地，被拒等，都能了解到 Go 语言的设计哲学和团队理念。</p>
<h3 id="还没有支持">还没有支持</h3>
<p>为什么 Go 语言的 XXX 功能没有支持？经典的像是 Go 的泛型、注解等功能。</p>
<p>还没有支持的可能性有三点，如下：</p>
<ol>
<li>还没有想清楚。</li>
<li>早就被拒绝了。</li>
<li>优先级不够高。</li>
</ol>
<p>实际上和我们业务迭代一样，Go 团队的人力资源有限，<strong>做事会有优先级</strong>。前文所提到的 Russ Cox 就是现在 Go 团队 Leader，每年也会开相关的会议讨论事项。</p>
<p>像是 Go 泛型，显然没有，也不会影响到 Go 在业务初期的短期发展，国内依然存有一定的占用率。2011 年没有想清楚，也就一直持续思考和尝试了&hellip;</p>
<p>而注解，或是你们想到的。很多在 go issues 其实早就被拒绝过多次，自然还没有支持，也是因为他不大可能直接出现了。</p>
<h3 id="推进的模式">推进的模式</h3>
<p>Go 在推进或偿还新技术改进时，现在采取的模式都是一样的。会先设计一个编译时可以指定的 “变量”。</p>
<p>例如：</p>
<ul>
<li>泛型的 G 变量。</li>
<li>Modules 的 GO111MODULE 变量。</li>
</ul>
<p>再在 Go 的不断迭代中，推进使用和反馈，再推进变量的默认开启，逐渐去除。</p>
<p>可以参考 GO111MODULE 的过程。</p>
<h2 id="总结">总结</h2>
<p>我们在学习很多语言、技能时，会以既有的知识去认知，再对新的对象建立新的认知树，很容易会有<strong>先入为主的认知行为</strong>。</p>
<p>但若没有及时思考，就很容易产生偏见。<strong>认为 XXX 是 XXX，你 Go 语言就应该是 XXX，这样是有失偏颇的</strong>。</p>
<p>就像我们行业经常讨论的，网上的 A 同学，35 岁被裁员了。那你我，35 岁就 100% 会下岗吗？</p>
<p>相反，Go 语言这 10+ 年来，基于自己的设计理念。保持了大致一贯的 less is more 设计理念，是值得赞许的。</p>
<p>我们要知道软件设计，是<strong>没有银弹</strong>的。Go 语言的设计理念，有好有坏，<strong>社区也有不少人对大道至简的理念嗤之以鼻</strong>。</p>
<p><strong>你又是怎么看待 Go 语言的呢</strong>，欢迎点赞、留言，一起来交流和讨论：）</p>


                                        
                                        
                                        
                                        <div class="rp4wp-related-posts">
                                            <h3>相关文章</h3>
                                            <ul>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/go-golang/">Go 和 Golang 有什么关系？</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/annotation/">Go：我有注解，Java：不，你没有！</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/type-after/">为什么 Go 语言把类型放在后面？</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/slice-leak/">Go 切片导致内存泄露，被坑两次了！</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.asia/posts/posts/go/when-gc/">Go 什么时候会触发 GC？</a>
                                                    </div>
                                                </li>
                                                
                                            </ul>
                                        </div>
                                        
                                        
                                    </div>

                                    
                                    
                                    

                                    
                                    <div class="post-meta">
                                        
                                        
                                        <div class="post-tags">
                                            <ul>
                                            
                                            <li>
                                                <a href="/tags/go" title="View all posts tagged match">go</a>
                                            </li>
                                            
                                            </ul>
                                        </div>
                                        
                                        
                                        <nav class="further-reading">
                                            
                                            <div class="previous">
                                                <span>&lt;&lt; Prev</span>
                                                <a href="https://www.lican.asia/posts/posts/go/go-golang/"
                                                    rel="prev">Go 和 Golang 有什么关系？</a> </div>
                                            
                                            
                                            <div class="next">
                                                <span>Next >></span>
                                                <a href="https://www.lican.asia/posts/posts/go/generics-apis/">出泛型后 API 怎么办？Go 开发者要注意了</a> 
                                            </div>
                                            
                                        </nav>
                                    </div>
                                    
                                    

                                    
                                    
                                    

                                </div>
                            </article>
                        </div>
                    </div>
                </section>
                <aside class="sidebar sidebar-primary" id="sidebar-primary" role="complementary">
    <h1 class="screen-reader-text">Sidebar</h1>
    

    
    
    <section id="text-2" class="widget widget_text">
        <div class="textwidget">
            
            <div id="profile">
                <div id="profile_picture"><img src="https://www.lican.asia/logo/logo.png"></div>
                <div id="profile_intro">
                    <p><span class="name">Lican</span></p>
                    <p class="intro">全栈开发者，爱好造轮子。</p>
                </div>
            </div>
            
            <p>
                <script type="text/javascript">
                    (function ($) {
                        $(document).ready(function () {
                            var menuPrimaryContainer = $('#menu-primary-container');
                            var profile = $('#text-2');
                            $('#toggle-navigation').click(function () {
                                if (menuPrimaryContainer.hasClass('open')) {
                                    profile.removeClass('open');
                                } else {
                                    profile.addClass('open');
                                }
                            });
                        });
                    })(jQuery);
                </script>
            </p>
        </div>
    </section>
    
    
    
    
    
    <section id="text-5" class="widget widget_text">
        <h2 class="widget-title">开源项目</h2>
        <div class="textwidget">
            <div id="projects" style="line-height: 22px;">
                
                <a href="https://github.com/idoubi/gonews"
                    target="_blank">gonews</a>: &nbsp;Daily news for golang<br>
                
                <a href="https://github.com/idoubi/sql2struct"
                    target="_blank">sql2struct</a>: &nbsp;Generate go struct according to SQL<br>
                
                <a href="https://github.com/idoubi/goz"
                    target="_blank">goz</a>: &nbsp;Request library used in golang<br>
                
        </div>
    </section>
    
    

    
    
    
    
    <section id="qrcode" class="widget widget_media_image">
        <h2 class="widget-title">微信公众号</h2>
        <img width="258" height="258"
            src="https://www.lican.asia/wechat/lican.png"
            class="image wp-image-5514  attachment-full size-full" alt=""
            style="max-width: 100%; height: auto;"
            sizes="(max-width: 258px) 100vw, 258px">
    </section>
    
    

    
    
    

    
    
    

    
    
    
    
</aside>
            </div>
        </div>

        <footer id="site-footer" class="site-footer" role="contentinfo">
    <div class="max-width">
    </div>
    <div class="footer">
        <div id="footercontent">
            © lican.asia All rights reserved<br/>
            Built with Hugo Theme <a href="https://github.com/idoubi/hugo-theme-period" target="_blank">Period</a>
        </div>
    </div>
</footer>

<script>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?e8351b6d4626d5881d439ea1f6184baa";
      var s = document.getElementsByTagName("script")[0]; 
      s.parentNode.insertBefore(hm, s);
    })();
</script>
    
    
    </div>
    
</body>

</html>